home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / os2 / cenvi2.arj / KEYPUSH.LIB < prev    next >
Text File  |  1993-12-16  |  12KB  |  358 lines

  1. // KeyPush.lib - Windows routines to control, or mimic, the pushing of
  2. //               keys on the keyboard.  This is one method of controlling
  3. //               windows applications.  The functions in this library work
  4. //               by sending keyboard messages to the focus window as if
  5. //               the key messages were actually being sent by Windows.
  6. //
  7. // The functions in this library are:
  8. //**KeyStroke([Holdkey1,HoldKey2,HoldKey3...]Character)
  9. //**KeyStroke([Holdkey1,HoldKey2,HoldKey3...]VirtualKeyCode)
  10. //**KeyStroke([Holdkey1,HoldKey2,HoldKey3...]KeyString)
  11. //   - Press and release a key or keys.  If HoldKeys are given then will mimic
  12. //     that these keys are pressed before KeyCode or KeyString, and then
  13. //     will press and release KeyCode or KeyString, and then will release
  14. //     HoldKeys in reverse order.
  15. //   Examples: To press the 'S' key: KeyStroke('S');
  16. //     To type a sentence: KeyStroke("On top of Old Smokey!");
  17. //     To type Alt-F1: KeyStroke(VK_ALT,VK_F1);
  18. //     To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R');
  19. //**VKeyDown(KeyCode)
  20. //   - Press virtual key for Window.
  21. //     Key is not released.
  22. //   Example: KeyDown(VK_SHIFT)
  23. //**VKeyUp(KeyCode)
  24. //   - Release key for focus Window.
  25. //   Example: KeyUp(VK_SHIFT)
  26. //**SpeedKeys(AsciiString[,DelayBetweenCharacters])
  27. //     Speed keys sends only WM_CHAR messages to an application and is much
  28. //     faster thatn KeyStroke(), but should only be used for regular ascii
  29. //     strings passed to applications that don't need to for each specific
  30. //     keystroke.  So, if KeyStroke() is too slow and you're entering a
  31. //     stretch of plain text, then use this function.  If DelayBetweenCharacters
  32. //     is supplied then this many milliseconds will be paused between each char.
  33. //
  34.  
  35.  
  36. KeyPushWindow = 0; // If this is 0, then will send messages to whatever window
  37.                    // has the focus.  If this is not-zero then will send
  38.                    // the FocuseWindow window handle.
  39.  
  40.  
  41. /*** Virtual key values *************************************************/
  42. #define VK_BUTTON1      0x01
  43. #define VK_BUTTON2      0x02
  44. #define VK_BUTTON3      0x03
  45. #define VK_BREAK        0x04
  46. #define VK_BACKSPACE    0x05
  47. #define VK_TAB          0x06
  48. #define VK_BACKTAB      0x07
  49. #define VK_NEWLINE      0x08
  50. #define VK_SHIFT        0x09
  51. #define VK_CTRL         0x0A
  52. #define VK_ALT          0x0B
  53. #define VK_ALTGRAF      0x0C
  54. #define VK_PAUSE        0x0D
  55. #define VK_CAPSLOCK     0x0E
  56. #define VK_ESC          0x0F
  57. #define VK_SPACE        0x10
  58. #define VK_PAGEUP       0x11
  59. #define VK_PAGEDOWN     0x12
  60. #define VK_END          0x13
  61. #define VK_HOME         0x14
  62. #define VK_LEFT         0x15
  63. #define VK_UP           0x16
  64. #define VK_RIGHT        0x17
  65. #define VK_DOWN         0x18
  66. #define VK_PRINTSCRN    0x19
  67. #define VK_INSERT       0x1A
  68. #define VK_DELETE       0x1B
  69. #define VK_SCRLLOCK     0x1C
  70. #define VK_NUMLOCK      0x1D
  71. #define VK_ENTER        0x1E
  72. #define VK_SYSRQ        0x1F
  73. #define VK_F1           0x20
  74. #define VK_F2           0x21
  75. #define VK_F3           0x22
  76. #define VK_F4           0x23
  77. #define VK_F5           0x24
  78. #define VK_F6           0x25
  79. #define VK_F7           0x26
  80. #define VK_F8           0x27
  81. #define VK_F9           0x28
  82. #define VK_F10          0x29
  83. #define VK_F11          0x2A
  84. #define VK_F12          0x2B
  85. #define VK_F13          0x2C
  86. #define VK_F14          0x2D
  87. #define VK_F15          0x2E
  88. #define VK_F16          0x2F
  89. #define VK_F17          0x30
  90. #define VK_F18          0x31
  91. #define VK_F19          0x32
  92. #define VK_F20          0x33
  93. #define VK_F21          0x34
  94. #define VK_F22          0x35
  95. #define VK_F23          0x36
  96. #define VK_F24          0x37
  97. #define VK_ENDDRAG      0x38
  98. #define VK_MENU         VK_F10
  99.  
  100.  
  101. KeyStroke(Key1,Key2,Key3/*etc...*/)
  102. {
  103.    _argCount = va_arg();
  104.    // if more than one parameter, then hold down all but the last one
  105.    for ( k = 1; k < _argCount; k++ )
  106.       KeyDown(va_arg(k-1));
  107.  
  108.    _key = va_arg(_argCount-1);
  109.    // Treat differently depending on whether Virtual Key Code, char, or string
  110.    if ( CMM_BYTE == DataType(_key) ) {
  111.       if ( 1 == DataDimension(_key) ) {
  112.          // send entire string one character at a time
  113.          for ( k = 0; _key[k]; k++ ) {
  114.             KeyDown(_key[k]);
  115.             KeyUp(_key[k]);
  116.          }
  117.       } else {
  118.          // send a single character out the port
  119.          KeyDown(_key);
  120.          KeyUp(_key);
  121.       }
  122.    } else {
  123.       // simply a virtual key code
  124.       KeyDown(_key);
  125.       KeyUp(_key);
  126.    }
  127.  
  128.    // if more than one parameter, then reverse release all but the last one
  129.    for ( k = 1; k < _argCount; k++ )
  130.       KeyUp(va_arg(_argCount-k-1));
  131. }
  132.  
  133. #define WM_CHAR   0x007a
  134. #define WM_TRANSLATEACCEL 0x004b
  135.  
  136. /* WM_CHAR fs field bits */
  137. #define KC_CHAR         0x0001
  138. #define KC_VIRTUALKEY   0x0002
  139. #define KC_SCANCODE     0x0004
  140. #define KC_SHIFT        0x0008
  141. #define KC_CTRL         0x0010
  142. #define KC_ALT          0x0020
  143. #define KC_KEYUP        0x0040
  144. #define KC_PREVDOWN     0x0080
  145. #define KC_LONEKEY      0x0100
  146. #define KC_DEADKEY      0x0200
  147. #define KC_COMPOSITE    0x0400
  148. #define KC_INVALIDCOMP  0x0800
  149. #define KC_TOGGLE       0x1000
  150. #define KC_INVALIDCHAR  0x2000
  151. #define KC_DBCSRSRVD1   0x4000
  152. #define KC_DBCSRSRVD2   0x8000
  153.  
  154. LatestKeyDown = FALSE; // True on call to key down, false on KeyUp
  155.  
  156. KeyDown(Key)
  157. {
  158.    // Save the current state of the 256-byte keyboard buffer
  159.    _keyTable = GetKeyboardTable();
  160.  
  161.    LatestKeyDown = TRUE;
  162.  
  163.    if ( CMM_BYTE == DataType(Key) ) {
  164.       // pushing just a character
  165.       fsflags = KC_CHAR;
  166.       usch = Key;
  167.       usvk = 0;
  168.    } else {
  169.       // pushing a virtual key
  170.       fsflags = KC_VIRTUALKEY;
  171.       usch = 0;
  172.       usvk = Key;
  173.       if ((_keyTable[Key] = (_keyTable[Key] | 0x80) ^ 1) & 0x01)
  174.          fsflags |= KC_TOGGLE;
  175.       SetKeyboardTable(_keyTable);
  176.    }
  177.  
  178.    if ( _keyTable[VK_SHIFT] & 0x80 )
  179.       fsflags |= KC_SHIFT;
  180.    if ( _keyTable[VK_ALT] & 0x80 )
  181.       fsflags |= KC_ALT;
  182.    if ( _keyTable[VK_CTRL] & 0x80 )
  183.       fsflags |= KC_CTRL;
  184.  
  185.    SendMessageAndAccelTable(fsflags | (1 << 16),usch | (usvk << 16));
  186. }
  187.  
  188. KeyUp(Key)
  189. {
  190.    // Save the current state of the 256-byte keyboard buffer
  191.    _keyTable = GetKeyboardTable();
  192.  
  193.    // set some fsflags based on keys currently pressed
  194.    fsflags = KC_KEYUP /*| KC_PREVDOWN*/;
  195.  
  196.    if ( CMM_BYTE == DataType(Key) ) {
  197.       // pushing just a character
  198.       fsflags |= KC_CHAR;
  199.       if ( (_keyTable[VK_CTRL] & 0x80)  &&  isalpha(Key) )
  200.          // convert to control character
  201.          usch = toupper(Key) - 'A' + 1;
  202.       else
  203.          usch = Key;
  204.       usvk = 0;
  205.    } else {
  206.       // pushing a virtual key
  207.       fsflags |= KC_VIRTUALKEY;
  208.       usch = 0;
  209.       usvk = Key;
  210.       if ((_keyTable[Key] &= 0x7F) & 0x01);
  211.          fsflags |= KC_TOGGLE;
  212.       SetKeyboardTable(_keyTable);
  213.    }
  214.  
  215.    if ( _keyTable[VK_SHIFT] & 0x80 )
  216.       fsflags |= KC_SHIFT;
  217.    if ( _keyTable[VK_ALT] & 0x80 )
  218.       fsflags |= KC_ALT;
  219.    if ( _keyTable[VK_CTRL] & 0x80 )
  220.       fsflags |= KC_CTRL;
  221.  
  222.    if ( LatestKeyDown )
  223.       fsflags |= KC_LONEKEY;
  224.    LatestKeyDown = FALSE;
  225.  
  226.    // send message to window that this key is being pressed
  227.    SendMessageAndAccelTable(fsflags | (1 << 16),usch | (usvk << 16));
  228. }
  229.  
  230. SpeedKeys(AsciiString,DelayBetweenCharacters)
  231. {
  232.    _skfocus = GetFocus();
  233.    _skdelay = ( 1 == va_arg() ) ? 0 : DelayBetweenCharacters ;
  234.    for ( c = AsciiString; c[0]; c++ ) {
  235.       Param1 = ((KC_CHAR | KC_LONEKEY)) | (1 << 16);
  236.       SendMessage(_skfocus,WM_CHAR,Param1,c[0]);
  237.       if ( _skdelay )
  238.          suspend( _skdelay );
  239.    }
  240. }
  241.  
  242.  
  243. /***********************************************************
  244.  *** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES ***
  245.  ***********************************************************/
  246.  
  247. #define HWND_DESKTOP    1
  248. #define ORD_WIN32SETKEYBOARDSTATETABLE   921
  249.  
  250. GetKeyboardTable()   // return 256 byte buffer for current keyboard state
  251. {
  252.    _table[255] = '\0';   // initialize 256-byte key table
  253.    DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
  254.                HWND_DESKTOP,_table,FALSE);
  255.    return(_table);
  256. }
  257.  
  258. SetKeyboardTable(_keyBuf)  // set the 256 byte buffer for current keyboard state
  259. {
  260.    DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
  261.                HWND_DESKTOP,_keyBuf,TRUE);
  262. }
  263.  
  264. GetFocus()  // return handle of Window with the focus
  265. {
  266.    #define ORD_WIN32QUERYFOCUS   817
  267.    return( KeyPushWindow
  268.          ? KeyPushWindow
  269.          : DynamicLink("PMWIN",ORD_WIN32QUERYFOCUS,BIT32,CDECL,HWND_DESKTOP) );
  270. }
  271.  
  272. SendMessage(WindowHandle,MessageID,Param1,Param2)
  273. {
  274.    #define ORD_WIN32SENDMSG   920
  275.    return PMDynamicLink("PMWIN",ORD_WIN32SENDMSG,BIT32,CDECL,
  276.                         WindowHandle,MessageID,Param1,Param2);
  277. }
  278.  
  279.  
  280. /***********************/
  281. /***  SHARED MEMORY ****/
  282.  
  283.    // Initialize pointer to shared memory that will be given to windowed
  284.    // applications to receive their accelerator messages.
  285.    #define QMSG_SIZE 32
  286.    #define ORD_DOS32ALLOCSHAREDMEM  300
  287.    #define PAG_COMMIT   0x10
  288.    #define OBJ_GIVEABLE 0x200
  289.    #define PAG_READ     0x1
  290.    #define PAG_WRITE    0x2
  291.  
  292.    assert( 0 == DynamicLink( "DOSCALLS", ORD_DOS32ALLOCSHAREDMEM, BIT32, CDECL,
  293.                              _acceleratorQMsg, NULL, QMSG_SIZE,
  294.                              PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE ) );
  295.    // zero all the bytes in this memory
  296.    for( _aqI = 0; _aqI < QMSG_SIZE; _aqI++ )
  297.       poke( _acceleratorQMsg + _aqI, 0 );
  298.    // Register function to free this memory when the current program exits
  299.    atexit("FreeAcceleratorMessageMemory");
  300.  
  301. FreeAcceleratorMessageMemory() // called at exit to free _acceleratorQMsg
  302. {
  303.    #define ORD_DOS32FREEMEM   304
  304.    assert( 0 == DynamicLink( "DOSCALLS", ORD_DOS32FREEMEM, BIT32, CDECL,
  305.                              _acceleratorQMsg ) );
  306. }
  307.  
  308.  
  309. /***********************************/
  310. /*** SEND KEY MESSAGES TO WINDOW ***/
  311.  
  312. _currentWinHandle = 0; // save which window was previously given shaed memory
  313. _currentProcessID;
  314. _currentAccelTable;
  315.  
  316. SendMessageAndAccelTable(Param1,Param2)
  317.    // Send this message and send an accelerator table message
  318. {
  319.    _focus = GetFocus();
  320.  
  321.    // see that the current window has been given access to the shared
  322.    // memory table memory
  323.    if ( _focus != _currentWinHandle ) {
  324.  
  325.       // This isn't the window we previously called. Must now get the
  326.       // Process ID of that window and give it access to the shared
  327.       // memory.
  328.       _currentWinHandle = _focus;
  329.  
  330.       // Get Process ID of current focus window
  331.       undefine(_currentProcessID);
  332.       #define ORD_WIN32QUERYWINDOWPROCESS  838
  333.       assert( DynamicLink( "PMWIN", ORD_WIN32QUERYWINDOWPROCESS, BIT32, CDECL,
  334.                            _focus, _currentProcessID, _PMAAT_dummy_tid ) );
  335.  
  336.       // Give our shared memory to that process ID
  337.       #define ORD_DOS32GIVESHAREDMEM   303
  338.       assert( 0 == DynamicLink( "DOSCALLS", ORD_DOS32GIVESHAREDMEM, BIT32, CDECL,
  339.                                 _acceleratorQMsg, _currentProcessID,
  340.                                 PAG_READ | PAG_WRITE) );
  341.    }
  342.  
  343.  
  344.    // copy the message to the globally allocated and shared memory
  345.    // build blob message to give to accelerator table
  346.    poke( _acceleratorQMsg, _focus, UWORD32 );
  347.    poke( _acceleratorQMsg+4, WM_CHAR, UWORD32 );
  348.    poke( _acceleratorQMsg+8, Param1, UWORD32 );
  349.    poke( _acceleratorQMsg+12, Param2, UWORD32 );
  350.  
  351.    // send message to window accelerator in case it wants to translate
  352.    SendMessage(_focus,WM_TRANSLATEACCEL,_acceleratorQMsg,0);
  353.    // send translated message to the window
  354.    SendMessage(peek(_acceleratorQMsg,UWORD32),peek(_acceleratorQMsg+4,UWORD32),
  355.                peek(_acceleratorQMsg+8,UWORD32),peek(_acceleratorQMsg+12,UWORD32));
  356. }
  357.  
  358.